import java.io.*;
import java.util.Random;
import org.kwis.msp.lcdui.Card;
import org.kwis.msp.lcdui.Display;
import org.kwis.msp.lcdui.Image;
import org.kwis.msp.lcdui.Graphics;
import org.kwis.msp.lcdui.EventQueue;

class TetrisCard extends Card implements Runnable{
    private Image gameoverImg;
    private Image scoreNumImg[];
    private Image scorePanelImg;
    private Image nextPanelImg;
	private Block block,nextBlock;
	private static int gameMode;
    private static final int GAMEONMODE = 1, GAMEOVERMODE = 2;
	private static int GAMESPEED = 1;
	private BackBoard backBoard;
    private int gameScore;
    private int currentBlockType, nextBlockType;
	private Thread thread;

    public TetrisCard() {
        try {
            gameoverImg = Image.createImage("/gmov.png");       // 이미지 초기화
            scorePanelImg = Image.createImage("/score.png");
           nextPanelImg = Image.createImage("/next.png");
            scoreNumImg = new Image[10];
            for(int i = 0; i < 10; i++)
                scoreNumImg[i] = Image.createImage("/" + i + ".png");
        } catch(IOException e) {
            System.out.println("LOAD Error : " + e);
        }
		block=getBlock();
		backBoard = new BackBoard();
		gameMode = GAMEONMODE;
    }
    
    protected boolean keyNotify(int type, int key){
		if (type == EventQueue.KEY_PRESSED) {    // 키코드를 게임액션으로 변환
			keyHandler(Display.getGameAction(key));
			return true;
		}
		return false;
    }

	public Block getBlock() {
        Random random = new Random();
		if(currentBlockType == 0)
            currentBlockType = ((int) (Math.abs(random.nextInt()) % 7)) + 1;
        else
            currentBlockType = nextBlockType;
        nextBlockType = ((int) (Math.abs(random.nextInt()) % 7)) + 1;
        nextBlock = new Block(nextBlockType);
        return new Block(currentBlockType);
	}

	private void showScorePanel(Graphics g) {
        g.drawImage(scorePanelImg, BackBoard.MAXWIDTH*6+5, 50, g.LEFT | g.TOP);
        int w, s = 0;
        for(int i = 4, j = 0; i >= 0; i--, j++) {
            w = (int)((gameScore - s) / power(10, i));
            s += (w * power(10, i));
            g.drawImage(scoreNumImg[w], BackBoard.MAXWIDTH*6+8 + (5 * j), 60, g.LEFT | g.TOP);
        }

    }
	
	private int power(int v, int n) {
        n--;
        if(n < 1) return v;
        return power(v, n) * v;
    }

    private void showNextPanel(Graphics g) {
        g.drawImage(nextPanelImg, BackBoard.MAXWIDTH*6+5, 10, g.LEFT | g.TOP);
        for(int i = 0; i < 4; i++)
            for(int j = 0; j < 4; j++)
                if((nextBlock.getCell())[i][j] != Block.NOCELL)
                    nextBlock.drawCell(g, nextBlock.getType(), (i * 6) + BackBoard.MAXWIDTH*6+6, (j * 6) + 20);
    }
    
    protected  void paint(Graphics g) {
        g.setColor(0, 0, 0);   // 배경 색상 지정(검정색)
        g.fillRect(0, 0, getWidth(), getHeight());   // 배경 색칠
        g.setColor(255, 255, 0);   // 오른쪽 경계선 그리기
        g.drawLine(BackBoard.MAXWIDTH*6+2, 10, BackBoard.MAXWIDTH*6+2, getHeight());
        showScorePanel(g);    // 점수판 그리기
        showNextPanel(g);     // next판 그리기
		backBoard.drawBackBoard(g);
		block.drawBlock(g);
		if(gameMode == GAMEOVERMODE) {
            g.drawImage(gameoverImg, getWidth() / 2, getHeight() / 2, g.HCENTER | g.VCENTER);
        }
    }

	public void run() {
        try {
            while(true) {
                if(gameMode == GAMEONMODE) {
                    gameOn();
                }
                Thread.sleep((int) (1000 / GAMESPEED));
            }
        }catch(Exception e) {  }
    }

	protected void keyHandler(int action) {
		if(gameMode != GAMEONMODE)
			return;

        switch(action) {
            case EventQueue.RIGHT : 
				block.move(1, 0);
				if(!block.moveOk(backBoard))
					block.move(-1, 0);
				else
					repaint();
				break;

            case EventQueue.LEFT : 
			    block.move(-1, 0);
			    if(!block.moveOk(backBoard))
				   block.move(1, 0);
			    else
				   repaint();
			    break;

			case EventQueue.DOWN : 
			    gameOn();
			    break;

			case EventQueue.UP : 
				block.rotate();
				if(!block.moveOk(backBoard))
					   for(int i = 0; i < 3; i++)
							block.rotate();
				else
					   repaint();
				break;
        }
		return;
	}
	
	private void gameOn() {
        block.move(0, 1);
		if(!block.moveOk(backBoard)) {
            block.move(0, -1);
            block.freeze(backBoard);
			checkALine();
			block = getBlock();
			if(!block.moveOk(backBoard))
                gameMode = GAMEOVERMODE;
            int newSpeed = (int) ((gameScore % 5000) / 1000);
            newSpeed++;
            GAMESPEED = newSpeed;
		}
		repaint();
    }

	public void checkALine() {
        boolean aline;
        int lines = 0;
        try {
            for(int i = BackBoard.MAXHEIGHT - 1; i >=0; i--) {
                aline = true;
                for(int j = 0; j < BackBoard.MAXWIDTH; j++) {
                    if((backBoard.getBoard())[j][i] == Block.NOCELL)
                        aline = false;
                }
                if(aline) {
                    for(int y = i; y >=1; y--)
                        for(int x = 0; x < BackBoard.MAXWIDTH; x++)
                            (backBoard.getBoard())[x][y] = (backBoard.getBoard())[x][y-1];
                    i++;
                    lines++;
                    repaint();
                }
            }
        } catch(Exception e) {
            System.out.println(e.getMessage());
        }
		switch(lines) {
            case 1 : gameScore += 200;
                     break;
            case 2 : gameScore += 500;
                     break;
            case 3 : gameScore += 900;
                     break;
            case 4 : gameScore += 2000;
                     break;
        }

        if(lines > 0) {
            repaint();
        }
	}
}


